<?php
/**
 * CK 开发框架
 * User: Clake
 * Date: 15/6/26
 * Time: 01:54
 */
namespace CK\Util;

use CK\Core\Component;
use CK\Ex\ExImage;
use CK\Util\IO\Directory;
use CK\Util\IO\File;

/**
 * 图片上传管理类
 * Class ImageUpload
 *
 * @package CK\Util
 */
class ImageUpload extends Component {
	private $file;
	private $file_name;
	private $save_path;
	private $image_type;
	private $image_mime;
	private $zoom;
	private $small;
	private $allowType = [
		'image/png'=>'png',
		'image/x-png'=>'png',
		'image/jpg'=>'jpg',
		'image/jpeg'=>'jpg',
		'image/pjpg'=>'jpg',
		'image/pjpeg'=>'jpg',
		'image/gif'=>'gif',
	];
	
	public $buildImageType = [
		'image/png'=>IMG_PNG,
		'image/jpeg'=>IMG_JPG,
		'image/jpg'=>IMG_JPG,
		'image/gif'=>IMG_GIF
	];

    private $_conf = [
        'domain'=>'',
        'main_path' => 'asset/ig',
        'tmp_path'=>'/asset/imgtmp',
        'img_type'=>[
            'user'=>'ur',
            'default'=>'df'
        ],
        //示例用变量名
        'global_var'=>[
            'main_path'=>'',
            'date'=>'',
            'time'=>'',
            'img_type'=>'',
            'img_name'=>'',
            'random'=>'',
            'size'=>'',
            'ext'=>''
        ],
        //图片连接地址示例
        'link_example'=>'/{main_path}/{date}/{img_type}',
        //图片名称示例
        'image_example'=>'{img_type}{time}{random}'
    ];

	public function __construct($field_name=null) {
        if ($field_name && isset($_FILES[$field_name])) {
            $this->file = $_FILES[$field_name];
            $this->image_mime = self::getImageMime($this->file['tmp_name']);
            $this->image_type = 'default';
        }
    }
	
//	public function __construct($field_name='',$image_type='default',$zoom=null,$small=null) {
//		if ($_FILES[$field_name]) {
//			$this->file = $_FILES[$field_name];
//			$this->image_mime = self::getImageMime($this->file['tmp_name']);
//		}
//		$this->image_type = $image_type?$image_type:'default';
//
//		$this->zoom = $zoom;
//		$this->small = $small;
//	}
	
	public function getExtName() {
		//$ext_name = strtolower(substr($this->file['name'],strrpos($this->file['name'], '.')+1));
		$ext_name = $this->allowType[$this->image_mime];
		if (!$ext_name) {
			throw new ExImage('image type denied!');
		}
		return $ext_name;
	}
	
	public function getUploadFileName() {
		$var = [
			'img_type'=>$this->_conf['img_type'][$this->image_type],
			'time'=>date('His'),
			'random'=>random_str(4)
		];
		
		$file_name = $this->_conf['image_example'];
		
		foreach ($var as $key => $value) {
			$file_name = str_replace($key, $value, $file_name);
		}
		
		$file_name = base64_encode($file_name);
		
		return $file_name.'.'.$this->getExtName();
	}
	
	public function getUploadDirPath($tmp = false) {
		$img_type = $this->_conf['img_type'][$this->image_type]?$this->_conf['img_type'][$this->image_type]:'df';
		$var = [
			'main_path'=>$this->_conf['main_path'],
			'date'=>date('ynj'),
			'img_type'=>$img_type
		];
		
		$dir_path = $this->_conf['link_example'];
		
		foreach ($var as $key=>$value) {
			$dir_path = str_replace('{'.$key.'}', $value, $dir_path);
		}
		if ($tmp) {
			$dir_path = str_replace('/', '_', $dir_path);
		}
		
		return $dir_path;
	}
	
	/**
	 * 等比例缩放图片
	 * @param int    $width
	 * @param int    $height
	 * @param string $src_path
	 * @param        $img_type
	 * @param bool   $is_new <是否生成新的缩放图片>
	 * @return void|string
	 */
	public function zoomImage($width,$height,$src_path,$img_type=IMG_PNG,$is_new=false) {
		list($src_width,$src_height) = getimagesize($src_path);
		
		if ($width && is_int($width)) {
			if ($width > $src_height) {
				
			}
		}
		
		if ($src_height < $height &&
			$src_width < $width) {
			return;
		}
		//先计算最大面
		if ($src_width > $src_height) {
			$old_line = $src_width;
			$new_line = $width;
		} else {
			$old_line = $src_height;
			$new_line = $height;
		}
		//计算纵容放比,并给出缩放的大小
		$percent = $new_line / $old_line;
		$m_width = $src_width * $percent;
		$m_height = $src_height * $percent;
		
		$small = @imagecreatetruecolor($m_width,$m_height);
		$oldim = @imagecreatefromstring(file_get_contents($src_path));
		imagecopyresampled($small,$oldim,0,0,0,0,$m_width,$m_height,imagesx($oldim),imagesy($oldim));
		imagedestroy($oldim);
		$path = substr($src_path, 0,strrpos($src_path,'/'));
		$file = substr($src_path, strrpos($src_path,'/')+1);
		$file = substr($file, 0,strrpos($file, '.'));
		if ($is_new) {
			$file .= '-'.$width.'x'.$height;
		}
		$out_file = $path."/".$file;
		if ($img_type === IMG_PNG) {
			$out_file .= '.png';
			imagepng($small,$out_file,9);
		} elseif ($img_type === IMG_JPG) {
			$out_file .= '.jpg';
			imagejpeg($small,$out_file,100);
		} elseif ($img_type === IMG_GIF) {
			$out_file .= '.gif';
			imagegif($small,$out_file);
		}
		imagedestroy($small);
		return $out_file;
	}
	
	public function moveTemp($name) {
		$find_name = substr($name, 0,strrpos($name, '.'));
		$file_exp = substr($name,strrpos($name, '.'));
		$source_path = APP_PATH.'.'.$this->_conf['tmp_path'];
		$dest_path = APP_PATH.".";
		$sp_path = explode('_', $find_name);
		$file_name = array_pop($sp_path);
		foreach ($sp_path as $dir) {
			if (!empty($dir)) {
				$dest_path .= "/$dir";
			}
		}
		if (!File::Exists($dest_path)) {
            Directory::Create($dest_path);
		}
		$file_list = glob($source_path.'/'.$find_name.'*');
		foreach ($file_list as $file) {
			if (is_file($file)) {
				$dest_file = substr($file,strpos($file, $file_name));
				if (@copy($file, $dest_path.'/'.$dest_file)) {
					unlink($file);
				}
			}
		}
		$uri = str_replace(APP_PATH.".", '', $dest_path);
		return $this->_conf['domain'].$uri.'/'.$file_name.$file_exp;
	}
	
	public function moveTempArray($file_arr) {
		$file_arr = json_decode($file_arr,true);
		$list = [];
		foreach ($file_arr as $file_name) {
			$list[$file_name] = $this->moveTemp($file_name);
		}
		return json_encode($list);
	}
	
	public function save($tmp = false) {
		$flag = false;
		$this->file_name = $this->getUploadFileName();
		$this->save_path = $this->getUploadDirPath($tmp);
		$file = "";
		if ($tmp) {
			$local_path = APP_PATH.'.'.$this->_conf['tmp_path'];
			$file = $this->save_path.'_'.$this->file_name;
		} else  {
			$local_path = APP_PATH.'.'.$this->save_path;
			$file = $this->file_name;
		}
		//验证保存路径是否存在,不存在就创建
		if (!File::Exists($local_path)) {
            Directory::Create($local_path);
		}
		if (move_uploaded_file($this->file['tmp_name'],$local_path.'/'.$file)) {
			$flag = [
				'img_path'=>$this->_conf['domain'].$this->save_path.'/'.$file,
				'img_name'=>$file
			];
			if (is_array($this->zoom)) {
				$this->zoomImage($this->zoom['width'],$this->zoom['height'],
						$local_path.'/'.$file,
						$this->buildImageType[$this->image_mime]);
			}
			
			if (is_array($this->small)) {
				foreach ($this->small as $img) {
					$small_file = $this->zoomImage($img['width'], $img['height'], 
						$local_path.'/'.$file,
						$this->buildImageType[$this->image_mime],
						true);
					$small_info = pathinfo($small_file);
					$small_name = explode('-',$small_info['filename']);
					$flag['small'][] = [
						'org_name'=>$small_info['basename'],
						'name'=>$small_name[0],
						'small'=>$small_name[1],
						'ext'=>$small_info['extension'],
						'url'=>$this->_conf['domain'].$this->_conf['tmp_path']
					];
				}
			}
		} else {
			throw new ExImage('Save image error!');
		}
		
		return $flag;
	}
	
	public static function getImageMime($fname) {
		$fh=fopen($fname,'rb');
		if ($fh) {
			$bytes6=fread($fh,6);
			fclose($fh);
			if ($bytes6===false) return false;
			if (substr($bytes6,0,3)=="\xff\xd8\xff") return 'image/jpeg';
			if ($bytes6=="\x89PNG\x0d\x0a") return 'image/png';
			if ($bytes6=="GIF87a" || $bytes6=="GIF89a") return 'image/gif';
			return 'application/octet-stream';
		}
		return false;
	}
	
	public static function deleteImage($url) {
        if (preg_match ( "/^http|https|ftp|file/is", $url )) {
            $path = parse_url($url)['path'];
        } else {
            $path = $url;
        }
        $params = pathinfo($path);
        $list = glob(APP_PATH.trim($params['dirname'],'/').'/'.$params['filename'].'*');
        foreach ($list as $file) {
            @unlink($file);
        }
	}

    /**
     * 截剪图片
     * @param string      $image_name 图片名称
     * @param int         $x          起始 X 坐标
     * @param int         $y          起始 Y 坐标
     * @param int         $width      裁剪宽
     * @param int         $height     裁剪高
     * @param null|array  $small      生成小图
     * @param array       $zoom       缩放大小
     *
     * @return bool
     */
	public function cutImage($image_name,$x,$y,$width,$height,$small=null,$zoom=['width'=>150,'height'=>150]) {
		$source_path = APP_PATH.'.'.$this->_conf['tmp_path'];
		$file_path = $source_path.'/'.$image_name;
		$img_type = $this->buildImageType[self::getImageMime($file_path)];
		//创建截剪图
		$im_cut = @imagecreatetruecolor($width,$height);
		$im_old = @imagecreatefromstring(file_get_contents($file_path));
		imagecopy($im_cut,$im_old,0,0,$x,$y,$width,$height);
		imagedestroy($im_old);
		$flag = false;
		if ($img_type === IMG_PNG) {
			$flag = imagepng($im_cut,$file_path,9);
		} elseif ($img_type === IMG_JPG) {
			$flag = imagejpeg($im_cut,$file_path,100);
		} elseif ($img_type === IMG_GIF) {
			$flag = imagegif($im_cut,$file_path);
		}
		imagedestroy($im_cut);
		
		if ($flag !== false && $small && is_array($small)) {
			foreach ($small as $sim) {
				$this->zoomImage($sim['width'], $sim['height'], $file_path, $img_type, true);
			}
		}
		
		if ($flag !== false && $zoom && is_array($zoom)) {
			$this->zoomImage($zoom['width'], $zoom['height'], $file_path, $img_type);
		}
		
		return $flag === false?false:true;
	}

    /**
     * 生成小图文件
     * @param $img_path string <图片路径>
     * @param $small array <生成小图尺寸>
     *
     * @return bool
     */
	public function smallImages($img_path,$small) {
		$ext = strtolower(substr($img_path, -3));
		$ext_list = [
			'png'=>IMG_PNG,
			'jpg'=>IMG_JPG,
			'gif'=>IMG_GIF
		];
		if (!isset($ext_list[$ext])) {
			return false;
		}
		if (preg_match("/http\\:\\/\\//i",$img_path)) {
			$img_path = str_replace($this->_conf['domain'], '', $img_path);
		}
		$src_path = APP_PATH.'.'.$img_path;

		if (File::Exists($src_path)) {
			foreach ($small as $sm) {
				$this->zoomImage($sm['width'], $sm['height'], $src_path ,$ext_list[$ext] ,true);
			}
			return true;	
		} else {
			return false;
		}
	}

    /**
     * 保存BASE64编码的图片
     * @param string $base64
     * @param json|string $options
     *
     * @return bool|string
     */
    public function saveFromBase64($base64,$options) {
        $this->image_type = $options['image_type'];
        $this->image_mime = substr($base64,5, strpos($base64,';')-5);
        $pos = substr($base64, strpos($base64,',')+1);
        $img = base64_decode($pos);
        $source_path = $this->getUploadDirPath();
        $img_name = $this->getUploadFileName();
        $img_full_path = $source_path.'/'.$img_name;
        $flag = File::Write(Directory::RP(APP_PATH.$img_full_path), $img);
        if ($flag) {
            if (isset($options['zoom'])) {
                $this->zoomImage($options['zoom']['width'],$options['zoom']['height'],Directory::RP(APP_PATH.$img_full_path),$this->buildImageType[$this->image_mime]);
            }
            if (isset($options['small'])) {
                $this->smallImages($img_full_path,$options['small']);
            }
            return $this->_conf['domain'].$img_full_path;
        } else {
            return false;
        }
    }

    /**
     * 保存一个远程地址的图片到本地
     * @param $url
     * @param $options
     *
     * @return bool|string
     */
	public function saveFromUrl($url,$options) {
        $data = Http::get($url);
        if (empty($data)) {
            return false;
        }

		$this->image_type = $options['image_type'];
		$this->image_mime = $data['headers']['Content-Type'];
		$img = $data['content'];
		$source_path = $this->getUploadDirPath();
		$img_name = $this->getUploadFileName();
		$img_full_path = $source_path.'/'.$img_name;
		$flag = File::Write(Directory::RP(APP_PATH.$img_full_path), $img);
		if ($flag) {
			if (is_array($options['zoom'])) {
				$this->zoomImage($options['zoom']['width'],$options['zoom']['height'],Directory::RP(APP_PATH.$img_full_path),$this->buildImageType[$this->image_mime]);
			}
			if (is_array($options['small'])) {
				$this->smallImages($img_full_path,$options['small']);
			}
			return $this->_conf['domain'].$img_full_path;
		} else {
			return false;
		}
	}
}